fix(packetrelay): add PacketListenerRelay idle deadlines#625
Conversation
Greptile SummaryThis PR bakes a 30-second write-idle deadline directly into
Confidence Score: 5/5Safe to merge — the core deadline logic is well-tested and the IPv4-mapped address fix is isolated to a single helper function. All changed paths have direct unit test coverage. The deadline mechanism uses standard net.PacketConn.SetDeadline semantics, the close-on-error path in ReceivePackets is exercised by TestPacketListenerRelayReceiveTimeoutClosesAssociation, and the IPv4-mapped fix is covered by the new TestDNSQueryRoutingWithIPv4MappedLocalResolver. The only open items are two stale doc comments on DelegatePacketRelay that do not affect runtime behaviour. No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Caller
participant PacketListenerRelay
participant packetListenerAssociation
participant net.PacketConn
Caller->>PacketListenerRelay: NewAssociation()
PacketListenerRelay->>net.PacketConn: ListenPacket()
PacketListenerRelay->>packetListenerAssociation: create(conn, writeIdleTimeout)
packetListenerAssociation->>net.PacketConn: SetDeadline(now + timeout)
PacketListenerRelay-->>Caller: sender, receiver
Caller->>+sender: SendPacket(p, dest)
sender->>packetListenerAssociation: refreshDeadline()
packetListenerAssociation->>net.PacketConn: SetDeadline(now + timeout)
sender->>packetListenerAssociation: getPacketConn()
sender->>net.PacketConn: WriteTo(p, dest)
sender-->>-Caller: nil
Note over packetListenerAssociation,net.PacketConn: If no SendPacket for writeIdleTimeout…
net.PacketConn-->>receiver: ReadFrom → timeoutErr
receiver->>packetListenerAssociation: close()
packetListenerAssociation->>net.PacketConn: Close()
receiver-->>Caller: timeoutErr
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Caller
participant PacketListenerRelay
participant packetListenerAssociation
participant net.PacketConn
Caller->>PacketListenerRelay: NewAssociation()
PacketListenerRelay->>net.PacketConn: ListenPacket()
PacketListenerRelay->>packetListenerAssociation: create(conn, writeIdleTimeout)
packetListenerAssociation->>net.PacketConn: SetDeadline(now + timeout)
PacketListenerRelay-->>Caller: sender, receiver
Caller->>+sender: SendPacket(p, dest)
sender->>packetListenerAssociation: refreshDeadline()
packetListenerAssociation->>net.PacketConn: SetDeadline(now + timeout)
sender->>packetListenerAssociation: getPacketConn()
sender->>net.PacketConn: WriteTo(p, dest)
sender-->>-Caller: nil
Note over packetListenerAssociation,net.PacketConn: If no SendPacket for writeIdleTimeout…
net.PacketConn-->>receiver: ReadFrom → timeoutErr
receiver->>packetListenerAssociation: close()
packetListenerAssociation->>net.PacketConn: Close()
receiver-->>Caller: timeoutErr
Reviews (3): Last reviewed commit: "refactor(packetrelay): make writeIdleTim..." | Re-trigger Greptile |
…ayFromPacketListener
Summary
PacketListenerRelayassociation a default 30s write-idle timeout usingnet.PacketConndeadlines.NewPacketRelayFromPacketListenerconstructor options; customize the timeout withPacketListenerRelay.SetWriteIdleTimeout.PacketListenerProxyadapter to use the nativePacketListenerRelaytimeout instead of wrapping withTimeoutPacketRelay.Why
PacketListenerRelayassociations need a timeout wherever they are used; otherwise dropped UDP packets can leave associations and goroutines alive indefinitely. Call sites were having to remember to wrap everyPacketListenerRelayinTimeoutPacketRelay, which made this easy to miss.The DNS intercept issue exposed another compatibility gap: some network stacks surface IPv4 UDP destinations in IPv4-mapped IPv6 form. Exact
netip.AddrPortequality meant a configured resolver like10.0.0.1:53did not match[::ffff:10.0.0.1]:53, so DNS queries could fall through to the default relay and time out.Testing
go test ./network/packetrelaygo test ./networkgo test ./network/dnsinterceptgo test ./...